#ifndef SF_DATE_TIME_H
#define SF_DATE_TIME_H

#include <stdint.h>
#include <algorithm>

class SFString;
class SFDateTime;
/**
 * @brief The SFDate class
 * @details SFDate对象包含公历中的日历日期，即年、月和日数字。
 *  它可以从系统时钟读取当前日期。它提供了比较日期和操作日期的函数。
 *  例如，可以对日、月、年进行加减
 */
class SFDate
{
public:
    SFDate() : m_jd(0)
    {}
    //! 传入的参数dt，是秒数
    SFDate(int64_t jd);
    SFDate(int year, int month, int day);

    //! 传入的参数dt，是秒数
    void setTime_t(int64_t dt);
    //! 返回的秒数
    int64_t toTime_t() const;

    //! 返回星期几 1~7
    int toWeek() const;

    //! 返回本月的第几天 1~31
    int toMonthDay() const;

    //! 返回月份 1 ~ 12
    int toMonth() const;

    //! 返回当前年分
    int toYear() const;

    SFString toString(const SFString &format) const;

    static SFDate fromString(const SFString &date);
    static SFDate currentDate();
    //! 获取今年某月有几天 0 ~ 11, 返回天数：1~31
    static int    getMonthDay(int mouth);

    bool operator!=(const SFDate &d) const { return m_jd != d.m_jd; }
    bool operator<(const SFDate &d)  const { return m_jd <  d.m_jd; }
    bool operator<=(const SFDate &d) const { return m_jd <= d.m_jd; }
    bool operator==(const SFDate &d) const { return m_jd == d.m_jd; }
    bool operator>(const SFDate &d)  const { return m_jd >  d.m_jd; }
    bool operator>=(const SFDate &d) const { return m_jd >= d.m_jd; }

    inline void clear() { m_jd = 0; }
private:
    int64_t m_jd; // 以天为单位
    friend class SFDateTime;
};

/**
 * @brief The SFTime class
 * @details SFTime度量的是一天之内的时间，一天有86400秒，所以结果总是在-86400000到86400000毫秒之间
 */
class SFTime
{
    explicit SFTime(int ms) : m_ds(ms)
    {}
public:
    SFTime() : m_ds(0)
    {}
    SFTime(int h, int m, int s = 0, int ms = 0);

    SFString toString(const SFString &format) const;

    int msecsTo(const SFTime &t) const;
    int secsTo(const SFTime &t) const;

    // 精确到毫秒
    static SFTime currentTime();
    // 精确到秒
    static SFTime currentTime2Sec();
    // 精确到分钟
    static SFTime currentTime2Minute();

    inline void clear() { m_ds = 0; }

    bool operator!=(const SFTime &d) const { return m_ds != d.m_ds; }
    bool operator<(const SFTime &d)  const { return m_ds <  d.m_ds; }
    bool operator<=(const SFTime &d) const { return m_ds <= d.m_ds; }
    bool operator==(const SFTime &d) const { return m_ds == d.m_ds; }
    bool operator>(const SFTime &d)  const { return m_ds >  d.m_ds; }
    bool operator>=(const SFTime &d) const { return m_ds >= d.m_ds; }

    void setSecond(int sec, int msec = 0);
    void setMSecond(int val);

    //! 返回当前毫秒
    int getMSecValue() const { return m_ds % 1000; }
private:
    enum TimeFlag { NullTime = -1 };

    int m_ds; // 单位是毫秒
    friend class SFDateTime;
};

/**
 * @brief The SFDateTime class
 * @details 模拟实现Qt SFDateTime类
 *  需要精确到毫秒
 */
class SFDateTime
{
public:
    SFDateTime()
        : mTime(0)
    {}
    //! 传入的参数dt，是毫秒
    SFDateTime(int64_t dt)
        : mTime(dt)
    {}
    SFDateTime(const SFTime &tm);
    SFDateTime(const SFDate &date);
    SFDateTime(const SFDate &date, const SFTime &tm);
    SFDateTime(const SFDateTime &dt)
        : mTime(dt.mTime)
    {}

    ~SFDateTime()
    {}

    SFDateTime addDays(int day) const;
    SFDate date();
    SFTime time();

    bool isNull() const { return 0 == mTime; }

    //! 传入的参数dt，是秒数
    void setTime_t(int64_t dt);
    //! 返回的秒数
    int64_t toTime_t() const;

    SFDateTime toLocalTime();
    SFDateTime toUTC();

    //! yyyy-MM-dd HH:mm:ss.z
    SFString toString(const SFString &format) const;

    static SFDateTime currentDateTimeUtc();
    static SFDateTime currentDateTime();
    //! 直接从UTC时间转化，不考虑时区
    static SFDateTime fromTime_t(int64_t val);
    //! 加上时区配偏移，一般不用
    static SFDateTime fromTime_tByTZ(int64_t val);

    //! 重新设置系统时区
    static void resetTimeZone();
    //! 获取当前系统的时区数字
    static int  getSysTimeZone();

    bool operator==(const SFDateTime &other) const
    {
        return mTime == other.mTime;
    }
    inline bool operator!=(const SFDateTime &other) const { return !(*this == other); }
    bool operator<(const SFDateTime &other) const
    {
        return mTime < other.mTime;
    }
    inline bool operator<=(const SFDateTime &other) const { return !(other < *this); }
    inline bool operator>(const SFDateTime &other) const { return other < *this; }
    inline bool operator>=(const SFDateTime &other) const { return !(*this < other); }
    inline void clear() { mTime = 0; }
    inline SFDateTime operator-(const SFDateTime &other) {
        return SFDateTime(this->mTime - other.mTime);
    }
private:
    int64_t mTime; // 以毫秒为单位
};

#endif // SF_DATE_TIME_H
